package cn.smile.business.basic.impl;

import cn.smile.bean.dto.basic.BasicItemDTO;
import cn.smile.bean.dto.basic.ExpenseItemDTO;
import cn.smile.bean.dto.basic.MyShopDTO;
import cn.smile.bean.dto.basic.PickerDTO;
import cn.smile.bean.entity.basic.ExpenseItem;
import cn.smile.bean.form.basic.item.ItemAddForm;
import cn.smile.bean.form.basic.item.ItemUpdateForm;
import cn.smile.bean.form.basic.item.QueryItemForm;
import cn.smile.business.basic.IExpenseItemService;
import cn.smile.business.basic.IItemToBasicService;
import cn.smile.business.basic.IMyShopService;
import cn.smile.commons.constant.CommonConstant;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.repository.basic.ExpenseItemMapper;
import cn.smile.utils.BeanCopy;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import jakarta.annotation.Resource;

import java.util.*;

@Slf4j
@Service
public class ExpenseItemServiceImpl extends BaseServiceImpl<ExpenseItemMapper, ExpenseItem> implements IExpenseItemService {
    private static final String DEL_ITEM_NAME_FORMAT = "%s[已删除]";

    @Resource
    private IMyShopService shopService;
    @Resource
    private IItemToBasicService toBasicService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addItem(ItemAddForm form) {
        log.info("[ConItemServiceImpl].[addItem] ------> 新增消费项目 Start, form = {}", JSON.toJSONString(form));
        ExpenseItem entity = BeanCopy.copyBean(form, ExpenseItem.class);
        super.addBaseCol(entity);
        if (ObjectUtils.isEmpty(form.getDefaultPrice())) {
            entity.setDefaultPrice(CommonConstant.DEFAULT_PRICE);
        }
        if (ObjectUtils.isEmpty(form.getSortNumber())) {
            entity.setSortNumber(NumberConstant.NINE_HUNDRED_AND_NINETY_NINE);
        }
        MyShopDTO shop = shopService.getMyShop();
        entity.setShopId(shop.getId());
        boolean flag = super.create(entity);
        if (flag) {
            toBasicService.saveCorrelation(entity.getId(), form.getBaseItemList());
        }
        log.info("[ConItemServiceImpl].[addItem] 新增消费项目 End, flag = {}", flag);
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateItem(ItemUpdateForm form) {
        log.info("[ConItemServiceImpl].[updateItem] ------> 更新消费项目 Start, form = {}", JSON.toJSONString(form));
        ExpenseItem entity = this.getBaseEntity(form.getId());
        if (entity.getPresetFlag()) {
            throw new BusinessException(MyResponseCode.PREDEFINED_ITEM_UPDATE_ERROR);
        }
        super.updateBaseCol(entity);
        entity.setItemName(form.getItemName());
        if (ObjectUtils.isEmpty(form.getDefaultPrice())) {
            entity.setDefaultPrice(CommonConstant.DEFAULT_PRICE);
        } else {
            entity.setDefaultPrice(form.getDefaultPrice());
        }
        if (!ObjectUtils.isEmpty(form.getSortNumber())) {
            entity.setSortNumber(form.getSortNumber());
        }
        boolean flag = super.update(entity);
        if (flag) {
            toBasicService.saveCorrelation(entity.getId(), form.getBaseItemList());
        }
        log.info("[ConItemServiceImpl].[updateItem] 更新消费项目 End, flag = {}", flag);
        return flag;
    }

    @Override
    public Map<String, ExpenseItemDTO> getItemMap(String shopId) {
        log.info("[ConItemServiceImpl].[getItemMap] ------> 根据店铺ID查询商品集合 Start, shopId = {}", shopId);
        Map<String, ExpenseItemDTO> dataMap = Maps.newHashMap();
        List<ExpenseItem> baseList = baseMapper.selectList(new QueryWrapper<ExpenseItem>().lambda().eq(ExpenseItem::getShopId, shopId));
        if (!CollectionUtils.isEmpty(baseList)) {
            List<ExpenseItemDTO> dataList = BeanCopy.copyList(baseList, ExpenseItemDTO.class);
            for (ExpenseItemDTO entity : dataList) {
                if (entity.getDeleted()) {
                    entity.setItemName(String.format(DEL_ITEM_NAME_FORMAT, entity.getItemName()));
                }
                dataMap.put(entity.getId(), entity);
            }
        }
        log.info("[ConItemServiceImpl].[getItemMap] ------> 根据店铺ID查询商品集合 End");
        return dataMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delItem(String id) {
        log.info("[ConItemServiceImpl].[delItem] ------> 删除消费项目 Start, id = {}", id);
        ExpenseItem entity = this.getBaseEntity(id);
        if (entity.getPresetFlag()) {
            throw new BusinessException(MyResponseCode.PREDEFINED_ITEM_DELETE_ERROR);
        }
        super.delBaseCol(entity);
        int updateNum = baseMapper.updateById(entity);
        if (updateNum > NumberConstant.ZERO) {
            toBasicService.delCorrelation(id);
        }
        log.info("[ConItemServiceImpl].[delItem] ------> 删除消费项目 End, updateNum = {}", updateNum);
        return updateNum > NumberConstant.ZERO;
    }

    @Override
    public IPage<ExpenseItemDTO> getItemPage(QueryItemForm form) {
        log.info("[ConItemServiceImpl].[getItemPage] ------> 分页查询消费项目 Start, form = {}", JSON.toJSONString(form));
        LambdaQueryWrapper<ExpenseItem> qw = this.getQueryParams(form);
        Page<ExpenseItem> basePage = baseMapper.selectPage(form.queryPage(), qw);
        IPage<ExpenseItemDTO> dataPage = BeanCopy.copyPage(basePage, ExpenseItemDTO.class);
        this.setDetail(dataPage.getRecords());
        log.info("[ConItemServiceImpl].[getItemPage] ------> 分页查询消费项目 End");
        return dataPage;
    }

    @Override
    public List<ExpenseItemDTO> getItemList(QueryItemForm form) {
        log.info("[ConItemServiceImpl].[getItemList] ------> 列表查询消费项目 Start, form = {}", JSON.toJSONString(form));
        LambdaQueryWrapper<ExpenseItem> qw = this.getQueryParams(form);
        List<ExpenseItem> baseList = baseMapper.selectList(qw);
        List<ExpenseItemDTO> dataList = BeanCopy.copyList(baseList, ExpenseItemDTO.class);
        this.setDetail(dataList);
        log.info("[ConItemServiceImpl].[getItemList] ------> 列表查询消费项目 End");
        return dataList;
    }

    @Override
    public Map<String, ExpenseItemDTO> getItemMap(QueryItemForm form) {
        Map<String, ExpenseItemDTO> dataMap = Maps.newHashMap();
        List<ExpenseItemDTO> itemList = this.getItemList(form);
        if (!CollectionUtils.isEmpty(itemList)) {
            for (ExpenseItemDTO entity : itemList) {
                dataMap.put(entity.getId(), entity);
            }
        }
        return dataMap;
    }

    @Override
    public ExpenseItemDTO getItemById(String id) {
        log.info("[ConItemServiceImpl].[getItemById] ------> 根据消费项目ID查询详情 Start, id = {}", id);
        ExpenseItem base = this.getBaseEntity(id);
        ExpenseItemDTO entity = BeanCopy.copyBean(base, ExpenseItemDTO.class);
        this.setDetail(Lists.newArrayList(entity));
        log.info("[ConItemServiceImpl].[getItemById] ------> 根据消费项目ID查询详情 End");
        return entity;
    }

    @Override
    public List<PickerDTO> getItemPickerList() {
        log.info("[ConItemServiceImpl].[getItemPickerList] ------> 选择器查询消费项目列表 Start");
        List<ExpenseItemDTO> itemList = this.getItemList(new QueryItemForm());
        List<PickerDTO> dataList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(itemList)) {
            itemList.sort(Comparator.comparing(ExpenseItemDTO::getSortNumber));
            for (ExpenseItemDTO item : itemList) {
                PickerDTO dto = new PickerDTO();
                dto.setValue(item.getId());
                dto.setLabel(item.getItemName());
                dataList.add(dto);
            }
        }
        log.info("[ConItemServiceImpl].[getItemPickerList] ------> 选择器查询消费项目列表 End");
        return dataList;
    }

    /**
     * 组织查询对象
     *
     * @param form 查询参数
     * @return 查询操作对象
     */
    private LambdaQueryWrapper<ExpenseItem> getQueryParams(QueryItemForm form) {
        LambdaQueryWrapper<ExpenseItem> qw = new QueryWrapper<ExpenseItem>().lambda().eq(ExpenseItem::getDeleted, Boolean.FALSE);
        MyShopDTO shop = shopService.getMyShop();
        qw.eq(ExpenseItem::getShopId, shop.getId());
        if (!ObjectUtils.isEmpty(form.getItemName())) {
            qw.like(ExpenseItem::getItemName, form.getItemName());
        }
        if (!ObjectUtils.isEmpty(form.getBasicId())) {
            List<String> itemIds = toBasicService.getByBasicId(form.getBasicId());
            qw.in(ExpenseItem::getId, itemIds);
        }
        if (!CollectionUtils.isEmpty(form.getIds())) {
            qw.in(ExpenseItem::getId, form.getIds());
        }
        return qw;
    }

    /**
     * 根据ID查询基本数据库对象
     *
     * @param id 数据ID
     * @return 查询结果对象
     */
    private ExpenseItem getBaseEntity(String id) {
        if (ObjectUtils.isEmpty(id)) {
            throw new BusinessException(MyResponseCode.ITEM_ID_NOT_NULL_ERROR);
        }
        ExpenseItem entity = baseMapper.selectOne(new QueryWrapper<ExpenseItem>().lambda().eq(ExpenseItem::getDeleted, Boolean.FALSE).eq(ExpenseItem::getId, id));
        if (ObjectUtils.isEmpty(entity)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        return entity;
    }

    /**
     * 写入消费项目扩展项目
     *
     * @param dataList 数据集合
     */
    private void setDetail(List<ExpenseItemDTO> dataList) {
        if (!CollectionUtils.isEmpty(dataList)) {
            List<String> ids = Lists.newArrayList();
            for (ExpenseItemDTO dto : dataList) {
                ids.add(dto.getId());
            }
            Map<String, List<BasicItemDTO>> basicMap = toBasicService.getByItemIds(ids);
            for (ExpenseItemDTO dto : dataList) {
                if (basicMap.containsKey(dto.getId())) {
                    List<BasicItemDTO> basicItemList = basicMap.get(dto.getId());
                    if (!CollectionUtils.isEmpty(basicItemList)) {
                        List<String> basicIds = Lists.newArrayList();
                        StringBuilder basicNames = new StringBuilder();
                        int index = NumberConstant.ZERO;
                        for (BasicItemDTO basic : basicItemList) {
                            index++;
                            basicIds.add(basic.getId());
                            basicNames.append(basic.getBaseName());
                            if (index < basicItemList.size()) {
                                basicNames.append(",");
                            }
                        }
                        dto.setBaseItemList(basicIds);
                        dto.setBaseItemNames(basicNames.toString());
                        dto.setBaseItemEntityList(basicItemList);
                    }
                }

                if (CollectionUtils.isEmpty(dto.getBaseItemList())) {
                    dto.setBaseItemList(Lists.newArrayList());
                    dto.setBaseItemEntityList(Lists.newArrayList());
                    dto.setBaseItemNames("");
                }
            }
        }
    }
}
